//
// Created by wkm on 2024-04-20.
//

#include "schedulekey.h"

void schedulekey::prc_read() {
    if (done == task_finished) {
        sc_uint<4> round = get_round.read();
        if (round >= 1 && round <= 11) {
            out_key_1 = temp_output[(round - 1) * 16];
            out_key_2 = temp_output[(round - 1) * 16 + 1];
            out_key_3 = temp_output[(round - 1) * 16 + 2];
            out_key_4 = temp_output[(round - 1) * 16 + 3];
            out_key_5 = temp_output[(round - 1) * 16 + 4];
            out_key_6 = temp_output[(round - 1) * 16 + 5];
            out_key_7 = temp_output[(round - 1) * 16 + 6];
            out_key_8 = temp_output[(round - 1) * 16 + 7];
            out_key_9 = temp_output[(round - 1) * 16 + 8];
            out_key_10 = temp_output[(round - 1) * 16 + 9];
            out_key_11 = temp_output[(round - 1) * 16 + 10];
            out_key_12 = temp_output[(round - 1) * 16 + 11];
            out_key_13 = temp_output[(round - 1) * 16 + 12];
            out_key_14 = temp_output[(round - 1) * 16 + 13];
            out_key_15 = temp_output[(round - 1) * 16 + 14];
            out_key_16 = temp_output[(round - 1) * 16 + 15];
            can_read = task_finished;
        }
    } else {
        can_read = computing_task;
    }
}


// 要支持重置，开始执行，内部计算44轮的状态、对外部呈现的状态、是否需要T转换及T转换
void schedulekey::prc_schedulekey() {
    if (reset) {
        round_num = 0;
        done = waiting_task;
        next_done = waiting_task;
        sbox_state_can_exe = false;
        first = true;
    }

    if (start && done == waiting_task) {
        temp_output[0] = init_key_1;
        temp_output[1] = init_key_2;
        temp_output[2] = init_key_3;
        temp_output[3] = init_key_4;
        temp_output[4] = init_key_5;
        temp_output[5] = init_key_6;
        temp_output[6] = init_key_7;
        temp_output[7] = init_key_8;
        temp_output[8] = init_key_9;
        temp_output[9] = init_key_10;
        temp_output[10] = init_key_11;
        temp_output[11] = init_key_12;
        temp_output[12] = init_key_13;
        temp_output[13] = init_key_14;
        temp_output[14] = init_key_15;
        temp_output[15] = init_key_16;
        round_num = 4;
        next_done = computing_task;
    }

    if (done == computing_task) {
        if (round_num < 44) {
            a = temp_output[(round_num - 1) * 4];
            b = temp_output[(round_num - 1) * 4 + 1];
            c = temp_output[(round_num - 1) * 4 + 2];
            d = temp_output[(round_num - 1) * 4 + 3];
            if (round_num % 4 == 0) {
                if (first) {
                    // 循环左移
                    temp = a;
                    a = b;
                    b = c;
                    c = d;
                    d = temp;
                    // 字节代换 TODO 可能有bug
                    addr1 = a;
                    addr2 = b;
                    addr3 = c;
                    addr4 = d;
                    first = false;
                    en_sbox_read = true;
                }
                if (sbox_done) {
                    a = data1;
                    b = data2;
                    c = data3;
                    d = data4;
                    // 轮常量异或
                    a = a ^ Rcon[round_num / 4 - 1];
                    sbox_state_can_exe = true;
                    first = true;
                    en_sbox_read = false;
                }
            } else {
                sbox_state_can_exe = true;
            }
            if (sbox_state_can_exe) {
                temp_output[round_num * 4] = a ^ temp_output[(round_num - 4) * 4];
                temp_output[round_num * 4 + 1] = b ^ temp_output[(round_num - 4) * 4 + 1];
                temp_output[round_num * 4 + 2] = c ^ temp_output[(round_num - 4) * 4 + 2];
                temp_output[round_num * 4 + 3] = d ^ temp_output[(round_num - 4) * 4 + 3];

                round_num += 1;
                sbox_state_can_exe = false;
            }
        } else {
            next_done = task_finished;
        }
    }

    done = next_done;
}